using AutoMapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using ShopPowerTemplate.Entities;
using ShopPowerTemplate.IoC;
using ShopPowerTemplate.Presentation.Mvc.Extensions;
using ShopPowerTemplate.Presentation.Mvc.Models;
using ShopPowerTemplate.Presentation.Mvc.ViewModels;
using ShopPowerTemplate.Services;

namespace ShopPowerTemplate.Presentation.Mvc.Controllers
{
	public partial class CustomerControllerBase : BaseController
	{
		#region Members

        protected ICustomerService _customerService;
        protected IReviewService _reviewService;
        protected IProductService _productService;
        protected IOrderService _orderService;
        protected IOrderStateService _orderStateService;
        protected IAddressService _addressService;

        #endregion

        #region Constructors

        public CustomerControllerBase(ICustomerService customerService, IReviewService reviewService, IProductService productService, IOrderService orderService, IOrderStateService orderStateService, IAddressService addressService)
        {
            _customerService = customerService;
            _reviewService = reviewService;
            _productService = productService;
            _orderService = orderService;
            _orderStateService = orderStateService;
            _addressService = addressService;
        }	

        #endregion

		#region Index

		// **************************************
        // URL: /Customer
        // **************************************
		public virtual ActionResult Index()
		{
			IndexCustomerViewModel viewModel = new IndexCustomerViewModel();
			ViewBag.PageIndex = this.GetPageIndex();
            ViewBag.PageSize = this.GetPageSize();
			ViewBag.SearchValue = this.GetSearchValue();
		
			return View(viewModel);
		}

		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult Load(string sidx, string sord, int page, int rows, string search, int mode = 1)
        {
            string searchValue = this.GetSearchValue();
            OrderBy orderBy = this.GetOrderBy();
            int pageIndex = this.GetPageIndex();
            int pageSize = this.GetPageSize();

            if (mode == (int)JQGridActionEnum.DefaultLoad)
            {                
                pageSize = (pageIndex + 1) * pageSize;
                pageIndex = 0;
            }
            else if (mode == (int)JQGridActionEnum.ShowMoreResults)
            {
                pageIndex = page;
                this.SetPageIndex(pageIndex);
            }
            else if (mode == (int)JQGridActionEnum.CustomSearch)
            {
                searchValue = search;
                this.SetSearchValue(searchValue);
                pageIndex = 0;
                this.SetPageIndex(pageIndex);
                orderBy = new OrderBy("", true);
                this.SetOrderBy(orderBy);
            }

            if (!string.IsNullOrEmpty(sidx)) // Sort request
            {
                orderBy = new OrderBy(sidx, sord == "asc");
                this.SetOrderBy(orderBy);
            }

            List<Customer> searchList = _customerService.Search(searchValue, orderBy.Property, orderBy.Ascending, pageIndex, pageSize);
            int count = _customerService.SearchCount(searchValue);
            
			if (!string.IsNullOrEmpty(sidx)) // Sort request
            {
                pageIndex = this.GetPageIndex();
            }

            var data = new
            {
                total = Math.Ceiling((float)count/(float)pageSize),        // Total pages
                page = pageIndex,      // Current page
                records = count,  // Total records
                rows = from customer in searchList     // Row data
                       select new
                       {
                           id = customer.Id,                
                           cell = new string[] {
						   
                                customer.FirstName,
								customer.LastName,
								customer.Email,
								customer.IsInactive.HasValue && customer.IsInactive.Value ? "1" : "0"
								
                           }
                       }
            };

            return Json(data);
        }

		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult Delete(int id)
        {
            try
            {
                _customerService.Remove(id);
            }
            catch (RemoveException ex)
            {
                Response.StatusCode = 500;
                return Content(ex.Message);
            }
            return Content(string.Empty);
        }
		
		public virtual FileContentResult Report()
        {
            IList<Customer> _customerList = _customerService.Search(this.GetSearchValue());            
            StringBuilder strBuilder = new StringBuilder();

            // columns
            strBuilder.AppendLine("FirstName;LastName;Email;IsInactive");

            // rows
            foreach (Customer customer in _customerList)
            {
                List<string> rowData = new List<string>() { customer.FirstName, customer.LastName, customer.Email, customer.IsInactive.ToString() };
                strBuilder.AppendLine(rowData.Aggregate((x, y) => x + ";" + y));
            }

			// encode report content
            System.IO.MemoryStream content = new System.IO.MemoryStream();
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(content, UTF8Encoding.UTF8))
                writer.Write(strBuilder.ToString());

            return File(content.ToArray(), "text/csv", "Customer.csv");
        }
		

		#endregion

		#region Create

		// *******************************************
        // URL: /Customer/Create
        // *******************************************
		[AcceptVerbs(HttpVerbs.Get)]
        public virtual ActionResult Create()
        {
            Customer customer = new Customer();
            CreateCustomerViewModel viewModel = Mapper.Map<Customer, CreateCustomerViewModel>(customer);
            
			return View(viewModel);
        }

		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult Create(CreateCustomerViewModel customerModel)
        {
            if (ModelState.IsValid)
            {
                Customer customer = new Customer();
                AutoMapper.Mapper.Map<CreateCustomerViewModel, Customer>(customerModel, customer);
 

				_customerService.Add(customer);

                return RedirectToAction("Edit", new { id = customer.Id});
            }
            else
            {

                return View(customerModel);
            }
		}
		

		#endregion

		#region Edit

		// *******************************************
        // URL: /Customer/Edit/id
        // *******************************************
		[AcceptVerbs(HttpVerbs.Get)]
        public virtual ActionResult Edit(int id)
        {
            Customer customer = _customerService.Find(id);
            EditCustomerViewModel viewModel = Mapper.Map<Customer, EditCustomerViewModel>(customer);
            
			return View(viewModel);
        }

		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult Edit(EditCustomerViewModel customerModel)
        {
            if (ModelState.IsValid)
            {
                Customer customer = _customerService.Find(customerModel.Id);
                AutoMapper.Mapper.Map<EditCustomerViewModel, Customer>(customerModel, customer);
                
				_customerService.Change(customer);

                return RedirectToAction("Index");
            }
            else
            {

                return View(customerModel);
            }
		}
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult LoadReviews(string sidx, string sord, int page, int rows, string search, int mode = 1, int masterId = 0)
        {
			Customer currentCustomer = _customerService.Find(masterId);
            List<Review> list = currentCustomer.Reviews.ToList();
			int count = list.Count();

			var data = new
            {
                total = 1,        // Total pages
                page = 1,      // Current page
                records = count,  // Total records
                rows = from review in list     // Row data
                       select new
                       {
                           id = review.Id,                
                           cell = new string[] {
                                review.Date.ToString(),
								review.Rating.ToString(),
								review.Comment,
								review.Product != null ? review.Product.IdentityDescription : string.Empty
                           }
                       }
            };

            // Return elements
            return Json(data);
        }

		public virtual ActionResult AddReviews(int masterId = 0)
        {
            PopUpReviewViewModel viewModel = new PopUpReviewViewModel();

			List<Product> allProduct = _productService.FindAll();
			viewModel.CustomerId = masterId;
			ViewBag.MasterProperty = "Customer";
			viewModel.ProductList = allProduct;
            ViewBag.Name = "AddReviews";

            return PartialView("~/Views/Review/PopUp.cshtml", viewModel);
        }
		
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult AddReviews(PopUpReviewViewModel reviewModel)
        {
            if (ModelState.IsValid)
            {
                Review reviews = new Review();
                AutoMapper.Mapper.Map<PopUpReviewViewModel, Review>(reviewModel, reviews);

				Customer customer = _customerService.Find(reviews.Customer.Id);
				_customerService.AddReviews(customer, reviews);
                
				Response.StatusCode = 200;
                return Content("OK", "text/plain");
            }
            else
            {
				List<Product> allProduct = _productService.FindAll();
				ViewBag.MasterProperty = "Customer";
				reviewModel.ProductList = allProduct;
            	ViewBag.Name = "AddReviews";


				return PartialView("~/Views/Review/PopUp.cshtml", reviewModel);
            }
        }	
		
		public virtual ActionResult EditReviews(int id, int masterId = 0)
        {
			Review review = _reviewService.Find(id);
            PopUpReviewViewModel viewModel = Mapper.Map<Review, PopUpReviewViewModel>(review);

			List<Customer> allCustomer = _customerService.FindAll();
			List<Product> allProduct = _productService.FindAll();
			viewModel.CustomerId = masterId;
			ViewBag.MasterProperty = "Customer";
			viewModel.ProductList = allProduct;
            ViewBag.Name = "EditReviews";

            return PartialView("~/Views/Review/PopUp.cshtml", viewModel);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult EditReviews(PopUpReviewViewModel reviewModel)
        {
            if (ModelState.IsValid)
            {
                Review review = _reviewService.Find(reviewModel.Id);
                AutoMapper.Mapper.Map<PopUpReviewViewModel, Review>(reviewModel, review);

                _reviewService.Change(review);

                Response.StatusCode = 200;
                return Content("OK", "text/plain");
            }
            else
            {
				List<Customer> allCustomer = _customerService.FindAll();
				List<Product> allProduct = _productService.FindAll();
				reviewModel.CustomerList = allCustomer;
				reviewModel.ProductList = allProduct;
				ViewBag.MasterProperty = "Customer";

                return PartialView("~/Views/Review/PopUp.cshtml", reviewModel);
            }
        }
		
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual void DeleteReviews(int id, int masterId = 0)
        {
			Review review = _reviewService.Find(id);
			Customer currentCustomer = _customerService.Find(masterId);

            _customerService.RemoveReviews(currentCustomer, review);
        }
			
		public virtual FileContentResult ReportReviews(int masterId = 0)
        {
			Customer currentCustomer = _customerService.Find(masterId);
            IList<Review> _reviewsList = currentCustomer.Reviews.ToList();          
            StringBuilder strBuilder = new StringBuilder();

            // columns
            strBuilder.AppendLine("Date;Rating;Comment;Product");

            // rows
            foreach (Review review in _reviewsList)
            {
                List<string> rowData = new List<string>() { review.Date.ToString(), review.Rating.ToString(), review.Comment, review.Product != null ? review.Product.IdentityDescription : string.Empty };
                strBuilder.AppendLine(rowData.Aggregate((x, y) => x + ";" + y));
            }

			// encode report content
            System.IO.MemoryStream content = new System.IO.MemoryStream();
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(content, UTF8Encoding.UTF8))
                writer.Write(strBuilder.ToString());

            return File(content.ToArray(), "text/csv", "Reviews.csv");
        }
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult LoadOrders(string sidx, string sord, int page, int rows, string search, int mode = 1, int masterId = 0)
        {
			Customer currentCustomer = _customerService.Find(masterId);
            List<Order> list = currentCustomer.Orders.ToList();
			int count = list.Count();

			var data = new
            {
                total = 1,        // Total pages
                page = 1,      // Current page
                records = count,  // Total records
                rows = from order in list     // Row data
                       select new
                       {
                           id = order.Id,                
                           cell = new string[] {
                                order.Reference,
								order.Date.ToString(),
								order.ShippingCost.ToString(),
								order.OrderState != null ? order.OrderState.IdentityDescription : string.Empty
                           }
                       }
            };

            // Return elements
            return Json(data);
        }

		public virtual ActionResult AddOrders(int masterId = 0)
        {
            PopUpOrderViewModel viewModel = new PopUpOrderViewModel();

			List<OrderState> allOrderState = _orderStateService.FindAll();
			viewModel.CustomerId = masterId;
			ViewBag.MasterProperty = "Customer";
			viewModel.OrderStateList = allOrderState;
            ViewBag.Name = "AddOrders";

            return PartialView("~/Views/Order/PopUp.cshtml", viewModel);
        }
		
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult AddOrders(PopUpOrderViewModel orderModel)
        {
            if (ModelState.IsValid)
            {
                Order orders = new Order();
                AutoMapper.Mapper.Map<PopUpOrderViewModel, Order>(orderModel, orders);

				Customer customer = _customerService.Find(orders.Customer.Id);
				_customerService.AddOrders(customer, orders);
                
				Response.StatusCode = 200;
                return Content("OK", "text/plain");
            }
            else
            {
				List<OrderState> allOrderState = _orderStateService.FindAll();
				ViewBag.MasterProperty = "Customer";
				orderModel.OrderStateList = allOrderState;
            	ViewBag.Name = "AddOrders";


				return PartialView("~/Views/Order/PopUp.cshtml", orderModel);
            }
        }	
		
		public virtual ActionResult EditOrders(int id, int masterId = 0)
        {
			Order order = _orderService.Find(id);
            PopUpOrderViewModel viewModel = Mapper.Map<Order, PopUpOrderViewModel>(order);

			List<Customer> allCustomer = _customerService.FindAll();
			List<OrderState> allOrderState = _orderStateService.FindAll();
			viewModel.CustomerId = masterId;
			ViewBag.MasterProperty = "Customer";
			viewModel.OrderStateList = allOrderState;
            ViewBag.Name = "EditOrders";

            return PartialView("~/Views/Order/PopUp.cshtml", viewModel);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult EditOrders(PopUpOrderViewModel orderModel)
        {
            if (ModelState.IsValid)
            {
                Order order = _orderService.Find(orderModel.Id);
                AutoMapper.Mapper.Map<PopUpOrderViewModel, Order>(orderModel, order);

                _orderService.Change(order);

                Response.StatusCode = 200;
                return Content("OK", "text/plain");
            }
            else
            {
				List<Customer> allCustomer = _customerService.FindAll();
				List<OrderState> allOrderState = _orderStateService.FindAll();
				orderModel.CustomerList = allCustomer;
				orderModel.OrderStateList = allOrderState;
				ViewBag.MasterProperty = "Customer";

                return PartialView("~/Views/Order/PopUp.cshtml", orderModel);
            }
        }
		
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual void DeleteOrders(int id, int masterId = 0)
        {
			Order order = _orderService.Find(id);
			Customer currentCustomer = _customerService.Find(masterId);

            _customerService.RemoveOrders(currentCustomer, order);
        }
			
		public virtual FileContentResult ReportOrders(int masterId = 0)
        {
			Customer currentCustomer = _customerService.Find(masterId);
            IList<Order> _ordersList = currentCustomer.Orders.ToList();          
            StringBuilder strBuilder = new StringBuilder();

            // columns
            strBuilder.AppendLine("Reference;Date;ShippingCost;OrderState");

            // rows
            foreach (Order order in _ordersList)
            {
                List<string> rowData = new List<string>() { order.Reference, order.Date.ToString(), order.ShippingCost.ToString(), order.OrderState != null ? order.OrderState.IdentityDescription : string.Empty };
                strBuilder.AppendLine(rowData.Aggregate((x, y) => x + ";" + y));
            }

			// encode report content
            System.IO.MemoryStream content = new System.IO.MemoryStream();
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(content, UTF8Encoding.UTF8))
                writer.Write(strBuilder.ToString());

            return File(content.ToArray(), "text/csv", "Orders.csv");
        }
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult LoadAddresses(string sidx, string sord, int page, int rows, string search, int mode = 1, int masterId = 0)
        {
			Customer currentCustomer = _customerService.Find(masterId);
            List<Address> list = currentCustomer.Addresses.ToList();
			int count = list.Count();

			var data = new
            {
                total = 1,        // Total pages
                page = 1,      // Current page
                records = count,  // Total records
                rows = from address in list     // Row data
                       select new
                       {
                           id = address.Id,                
                           cell = new string[] {
                                address.AddressLine1,
								address.AddressLine2,
								address.City,
								address.StateProvince,
								address.PostalCode,
								address.Country,
								address.IsBilling? "1" : "0"
                           }
                       }
            };

            // Return elements
            return Json(data);
        }

		public virtual ActionResult AddAddresses(int masterId = 0)
        {
            PopUpAddressViewModel viewModel = new PopUpAddressViewModel();

			viewModel.CustomerId = masterId;
			ViewBag.MasterProperty = "Customer";
            ViewBag.Name = "AddAddresses";

            return PartialView("~/Views/Address/PopUp.cshtml", viewModel);
        }
		
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult AddAddresses(PopUpAddressViewModel addressModel)
        {
            if (ModelState.IsValid)
            {
                Address addresses = new Address();
                AutoMapper.Mapper.Map<PopUpAddressViewModel, Address>(addressModel, addresses);

				Customer customer = _customerService.Find(addresses.Customer.Id);
				_customerService.AddAddresses(customer, addresses);
                
				Response.StatusCode = 200;
                return Content("OK", "text/plain");
            }
            else
            {
				ViewBag.MasterProperty = "Customer";
            	ViewBag.Name = "AddAddresses";


				return PartialView("~/Views/Address/PopUp.cshtml", addressModel);
            }
        }	
		
		public virtual ActionResult EditAddresses(int id, int masterId = 0)
        {
			Address address = _addressService.Find(id);
            PopUpAddressViewModel viewModel = Mapper.Map<Address, PopUpAddressViewModel>(address);

			List<Customer> allCustomer = _customerService.FindAll();
			viewModel.CustomerId = masterId;
			ViewBag.MasterProperty = "Customer";
            ViewBag.Name = "EditAddresses";

            return PartialView("~/Views/Address/PopUp.cshtml", viewModel);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult EditAddresses(PopUpAddressViewModel addressModel)
        {
            if (ModelState.IsValid)
            {
                Address address = _addressService.Find(addressModel.Id);
                AutoMapper.Mapper.Map<PopUpAddressViewModel, Address>(addressModel, address);

                _addressService.Change(address);

                Response.StatusCode = 200;
                return Content("OK", "text/plain");
            }
            else
            {
				List<Customer> allCustomer = _customerService.FindAll();
				addressModel.CustomerList = allCustomer;
				ViewBag.MasterProperty = "Customer";

                return PartialView("~/Views/Address/PopUp.cshtml", addressModel);
            }
        }
		
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual void DeleteAddresses(int id, int masterId = 0)
        {
			Address address = _addressService.Find(id);
			Customer currentCustomer = _customerService.Find(masterId);

            _customerService.RemoveAddresses(currentCustomer, address);
        }
			
		public virtual FileContentResult ReportAddresses(int masterId = 0)
        {
			Customer currentCustomer = _customerService.Find(masterId);
            IList<Address> _addressesList = currentCustomer.Addresses.ToList();          
            StringBuilder strBuilder = new StringBuilder();

            // columns
            strBuilder.AppendLine("AddressLine1;AddressLine2;City;StateProvince;PostalCode;Country;IsBilling");

            // rows
            foreach (Address address in _addressesList)
            {
                List<string> rowData = new List<string>() { address.AddressLine1, address.AddressLine2, address.City, address.StateProvince, address.PostalCode, address.Country, address.IsBilling.ToString() };
                strBuilder.AppendLine(rowData.Aggregate((x, y) => x + ";" + y));
            }

			// encode report content
            System.IO.MemoryStream content = new System.IO.MemoryStream();
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(content, UTF8Encoding.UTF8))
                writer.Write(strBuilder.ToString());

            return File(content.ToArray(), "text/csv", "Addresses.csv");
        }
		

		#endregion

		#region Details

		// *******************************************
        // URL: /Customer/Details/id
        // *******************************************
		[AcceptVerbs(HttpVerbs.Get)]
        public virtual ActionResult Details(int id)
        {
            Customer customer = _customerService.Find(id);
            DetailsCustomerViewModel viewModel = Mapper.Map<Customer, DetailsCustomerViewModel>(customer);
            
			return View(viewModel);
        }
		

		#endregion
	}
}
